package com.siss.tenancy.user.utils;

import com.siss.tenancy.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisTenantUtil {

	public static final Long TIMEOUT = 300L;
	
	@Autowired
	private RedisTemplate redisTemplate;

	/**
	 * 批量删除对应的value
	 * 
	 * @param keys
	 */
	public void remove(final String... keys) {
		for (String key : keys) {
			remove(key);
		}
	}

	/**
	 * 批量删除key
	 * 
	 * @param pattern
	 */
	public void removePattern(final String pattern) {
		Set<Serializable> keys = redisTemplate.keys(pattern);
		if (keys.size() > 0) {
			redisTemplate.delete(keys);
		}
	}

	/**
	 * 删除对应的value
	 * 
	 * @param key
	 */
	public void remove(final String key) {
		if (exists(key)) {
			redisTemplate.delete(key);
		}
	}

	/**
	 * 判断缓存中是否有对应的value
	 * 
	 * @param key
	 * @return
	 */
	public boolean exists(final String key) {
		return redisTemplate.hasKey(key);
	}

	/**
	 * 读取缓存
	 * 
	 * @param key
	 * @return
	 */
	public Object get(final String key) {
		Object result = null;
		ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
		result = operations.get(key);
		return result;
	}

	/**
	 * 写入缓存
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(final String key, Object value) {
		boolean result = false;
		try {
			ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 写入缓存
	 * 
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean set(final String key, Object value, Long expireTime) {
		boolean result = false;
		try {
			ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
			operations.set(key, value);
			redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/** 写入缓存 Hash */
	public boolean setHash(final String key, Map<String, Object> value) {
		boolean result = false;
		try {
			HashOperations<String, String, Object> operations = redisTemplate.opsForHash();
			operations.putAll(key, value);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/** 读取缓存 Hash */
	public Object getHash(final String key, String hkey) {
		Object result = null;
		HashOperations<String, String, Object> operations = redisTemplate.opsForHash();
		result = operations.get(key, hkey);
		return result;
	}
	
	/** 读取全部Hash */
	public Object getHashAll(final String hkey) {
		Object result = null;
		HashOperations<String, String, Object> operations = redisTemplate.opsForHash();
		result = operations.entries(hkey);
		return result;
	}
	
	/** 根据key删除缓存 */
	public boolean remove(final String key, String hkey) {

		try {

			HashOperations<String, String, Object> operations = redisTemplate.opsForHash();
			Long delete = operations.delete(key, hkey);
			if (delete > 0) {
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public void leftPush(String key,String value)throws Exception{
		ListOperations<Serializable, Object> operations = redisTemplate.opsForList();
		Long result = operations.leftPush(key,value);
		if(null == result){
			throw new Exception("缓存失败");
		}
	}
	public String rightPop(String key)throws Exception{
		ListOperations<Serializable, Object> operations = redisTemplate.opsForList();
		String result = (String)operations.rightPop(key);
		return result;
	}

	/**
	 *
	 * 功能描述：获取redis分布式锁，当锁过期后第一次进来获取锁成功，当不过期，另外一个服务
     * 进来调用getSet方法只会更新value值，并不会获取锁
	 * 作   者： liyp
	 * 创建时间： 2019/9/24 15:55
	 * 参数: [key, value] value在这里未一个时间戳
	 *  返回值： java.lang.Boolean
	 */
	public Boolean getLock(final String key, Object value){
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        Object o = operations.get(key);
        boolean exist = false;
        if(null == o){
			exist = setnx(key,value);
			if(exist){
				redisTemplate.expire(key,3600,TimeUnit.SECONDS);
				return exist;
			}
		}
        //先执行getAndSet
		String oldValue = String.valueOf(operations.getAndSet(key,value));
		String expireValue = String.valueOf(o);
        Long valueLong = Long.parseLong(expireValue);
		if (valueLong.longValue()<System.currentTimeMillis()) {
			if(!StringUtil.isEmpty(oldValue) && oldValue.equals(expireValue)){
				redisTemplate.expire(key,3600,TimeUnit.SECONDS);
				return true;
			}
		}
		return false;
    }

    /**
     *
     * 功能描述：如果不存在就增加value
     * 作   者： liyp
     * 创建时间： 2019/9/24 16:36
     * 参数: [key, value]
     *  返回值： boolean
     */
    public boolean setnx(final String key, Object value){
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        boolean success = operations.setIfAbsent(key, value);
        if(success){
			redisTemplate.expire(key,3600,TimeUnit.SECONDS);
		}
        return success;
    }

}
